import { computed, onMounted, reactive, ref } from 'vue'
import _ from 'lodash'
import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'

import qs from 'qs'
import { saveAs } from 'file-saver'

import 'element-plus/theme-chalk/el-message.css'
import 'element-plus/theme-chalk/el-message-box.css'
import 'element-plus/theme-chalk/el-loading.css'

import { getFormat } from '@/utils/app'

export default function useTable(
  proxy,
  options = {
    model: {
      idProp: 'id',
      tipsProp: undefined,
    },
    view: {
      refreshView: undefined
    },

    queryForm: {
      ref: 'queryFormRef',
      params: {}
    },
    table: {
      ref: 'tableRef',
      columnSettingRef: 'columnSettingRef',
      columns: [],
      pageSizes: [10, 20, 50, 100, 200, 500],
      clickRow: { before: undefined, after: undefined },
      persist: undefined
    },
    action: {
      query: {
        api: undefined,
        before: undefined,
        after: undefined,
        resoleParam: undefined,
        reset: { after: undefined }
      },
      delete: {
        api: undefined,
        before: undefined,
        after: undefined,
        tips: '删除成功',
      },
      download: {
        ref: undefined,
        api: undefined,
        before: undefined,
        after: undefined
      },
      upload: {
        ref: undefined,
        api: undefined,
        fetchHeaderApi: undefined,
        before: undefined,
        after: undefined
      }
    }
  }
) {
  // 设置默认值(测试)
  options = _.defaultsDeep(options, {
    action: {
      delete: {
        tips: '删除成功'
      }
    }
  })

  const tableModel = reactive({
    pageSizes: options.table.pageSizes || [10, 20, 50, 100, 200],
    pageNum: 1,
    pageSize: options.table.pageSizes[0] || 20,
    orderProps: [],
    total: 0,
    pagerCount: 7,
    layout: 'total, sizes, prev, pager, next, jumper',
    stripe: true,
    border: true,
    index: false,
    size: 'default',
    columnSetting: defaultColumns(),
    columns: undefined,
    clickRow: null,
    selectedRow: [],
    data: []
  })

  tableModel.columns = computed(() => {
    const result = []
    // console.log(tableModel)
    for (const item of tableModel.columnSetting) {
      if (item.show) {
        if (item.formatter) {
          // formatter转换为具体的function
          item.formatter = getFormat(item.formatter)
        }
        result.push(item)
      }
    }
    return result
  })

  const disabled = reactive({
    edit: true,
    delete: true
  })

  const loading = reactive({
    table: false,
    query: false,
    delete: false,
    submit: false,
    upload: false,
    download: false
  })

  const queryModel = ref(defaultQueryFormData())

  function defaultColumns() {
    return options.table.columns ? _.cloneDeep(options.table.columns) : []
  }

  function resetColumnSetting() {
    tableModel.columnSetting = defaultColumns()
  }

  function saveColumnSetting(val) {
    tableModel.columnSetting = val
    // console.log(tableModel.columnSetting, 'options.table.columns')
    if (_.isFunction(options.table?.persist)) {
      options.table.persist(val)
    }
  }

  function pageNumChange(newPageNum) {
    // console.log(newPageNum, 'newPageNum')
    tableModel.pageNum =
      (newPageNum - 1) * tableModel.pageSize > tableModel.total ? 1 : newPageNum
    fetchTableData()
  }

  function pageSizeChange() {
    fetchTableData()
  }

  function clickTableRow(row) {
    // console.log(row, 'clickTableRow')
    if (_.isFunction(options.table?.clickRow?.before)) {
      options.table.clickRow.before(row)
    }
    tableModel.clickRow = row
    if (_.isFunction(options.table?.clickRow?.after)) {
      // console.log('clickTableRow callback')
      options.table.clickRow.after(row)
    }
  }

  function handleQuery() {
    loading.query = true
    proxy.$refs[options.queryForm.ref].validate((valid, prop) => {
      if (!valid) {
        loading.query = false
        console.log(prop, valid)
        return
      }
      fetchTableData()
    })
  }

  function resetQuery() {
    // 校验规则重置
    proxy.$refs[options.queryForm.ref].resetFields()
    queryModel.value = defaultQueryFormData()
    loading.query = false
    if (_.isFunction(options.queryForm.reset?.after)) {
      options.queryForm.reset.after()
    }
  }

  function defaultQueryFormData() {
    return options.queryForm.params ? _.cloneDeep(options.queryForm.params) : {}
  }

  function fetchTableData() {
    let param = _.cloneDeep(queryModel.value)
    param.pageNum = tableModel.pageNum
    param.pageSize = tableModel.pageSize
    param.sorts = tableModel.orderProps
    // console.log(param, 'param')

    if (_.isFunction(options.action.query?.before)) {
      options.action.query.before(param)
    }

    // 额外的数据转换
    if (_.isFunction(options.action.query?.resoleParam)) {
      param = options.action.query.resoleParam(param)
    }

    loading.table = true
    options.action.query
      .api(param)
      .then((res) => {
        loading.table = false
        loading.query = false
        tableModel.data = res.data
        tableModel.total = res.total
        if (_.isFunction(options.action.query?.after)) {
          options.action.query.after(res)
        }
      })
      .catch(() => {
        loading.table = false
        loading.query = false
      })
  }

  function handleDelete(row) {
    const arrayToDelete = row ? [row] : tableModel.selectedRow
    // console.log(arrayToDelete)
    let size = arrayToDelete.length
    if (size === 0) {
      return
    }
    const title = '共删除' + size + '条数据'
    let message = ''
    if (options.model?.tipsProp && size < 20) {
      message += arrayToDelete
        .map((row) => row[options.model.tipsProp])
        .join(',')
    }
    // 弹窗确认
    ElMessageBox.confirm(message, title, {
      confirmButtonText: '删除',
      confirmButtonClass: 'el-button--danger',
      cancelButtonText: '取消',
      type: 'error'
    })
      .then(() => {
        loading.delete = true
        if (_.isFunction(options.action.delete?.before)) {
          options.action.delete.before()
        }
        const ids = arrayToDelete.map((item) => item[options.model.idProp])
        options.action.delete
          .api(ids)
          .then(() => {
            loading.delete = false
            proxy.$modal.msgSuccess(options.action.delete.tips)
            _.isFunction(options.view?.refreshView) ? options.view.refreshView() : fetchTableData()        
            if (_.isFunction(options.action.delete?.after)) {
              options.action.delete.after()
            }
          })
          .catch(() => {
            loading.delete = false
          })
      })
      .catch((action) => {
        // console.log(action, 'confirm action')
      })
  }

  function handleExport(exportAll = false) {
    const downloadLoadingInstance = ElLoading.service({
      text: '正在下载数据，请稍候',
      background: 'rgba(0, 0, 0, 0.7)'
    })
    // todo 全部放到param参数中，去除该参数
    const pageParam = exportAll
      ? { pageNum: 1, pageSize: 10000 }
      : { pageNum: tableModel.pageNum, pageSize: tableModel.pageSize }
    const param = '?' + qs.stringify(pageParam)

    const data = queryModel.value
    data.pageNum = tableModel.pageNum
    data.pageSize = tableModel.pageSize
    data.sorts = tableModel.orderProps
    options.action.download
      .api(data, param)
      .then(async ({ data, resHeader }) => {
        if (data.type !== 'application/vnd.ms-excel') {
          downloadLoadingInstance.close()
          const text = await data.text()
          ElMessage.error(text)
          return
        }
        const blob = new Blob([data])
        const fileName = decodeURI(
          resHeader.substr(
            resHeader.indexOf('filename=') + 9,
            +resHeader.length
          ) || 'undefined.xlsx'
        )
        saveAs(blob, fileName)
        downloadLoadingInstance.close()
      })
      .catch((e) => {
        // console.error(e)
        ElMessage.error('下载文件出现错误，请联系管理员！')
        downloadLoadingInstance.close()
      })
  }

  const upload = reactive({
    show: false,
    title: '模板导入',
    limit: 1,
    headers: null,
    action: import.meta.env.VITE_APP_BASE_API + options.action.upload?.api,
    isUploading: false,
    excelHeaders: null,
    param: {
      exceptionStrategy: null,
      saveResult: null,
      keys: null,
      keyStrategy: null
    }
  })

  function handleUpload() {
    upload.show = true
    // 加载excel表头请求
    options.action.upload.fetchHeaderApi().then((res) => {
      upload.excelHeaders = res.data
    })
  }

  function closeUpload() {
    upload.show = false
  }

  function handleFileUploadProgress() { }

  function handleFileSuccess(uploadProxy) {
    upload.show = false
    uploadProxy.$refs[options.action.upload.ref].clearFiles()
    // todo 等待完全导入再刷新
    _.isFunction(options.view?.refreshView) ? options.view.refreshView() : fetchTableData()
  }

  function submitUpload(uploadProxy) {
    upload.action =
      import.meta.env.VITE_APP_BASE_API +
      options.action.upload.api +
      '?' +
      qs.stringify(upload.param)
    // todo 打印异常
    uploadProxy.$refs[options.action.upload.ref].submit()
  }

  onMounted(() => {
    console.log('useTable hook mounted!')
  })

  function handleSelectionChange(selection) {
    tableModel.selectedRow = selection
    disabled.edit = selection.length === 0 || selection.length > 1
    disabled.delete = selection.length === 0
  }

  function handleSortChange({ column, prop, order }) {
    if (prop === null) {
      // todo 点击第三次时 所有属性为null，element plus bug
      tableModel.orderProps.length = 0
      fetchTableData()
      return
    }

    // 取消排序
    if (order === null) {
      if (tableModel.orderProps.length === 1) {
        tableModel.orderProps = []
        return
      }
      const index = tableModel.orderProps.findIndex((item) => {
        return item.prop === prop
      })
      tableModel.orderProps.splice(index, 1)
      return
    }

    // 排序字段更新
    for (const item of tableModel.orderProps) {
      if (item.prop === prop) {
        item.order = order === 'descending' ? 1 : 0
        return
      }
    }

    // 添加排序字段
    tableModel.orderProps.push({
      prop: prop,
      order: order === 'descending' ? 1 : 0
    })

    // console.log(column, prop, order, tableModel.orderProps ,'handleSortChange')
    fetchTableData()
  }

  // 多列排序表头
  function handleHeaderCellClass({ row, column, rowIndex, columnIndex }) {
    // console.log(column, tableModel.orderProps)
    if (tableModel.orderProps?.length === 0) {
      column.order = undefined
      return
    }
    for (const item of tableModel.orderProps) {
      if (column.property === item.prop) {
        column.order =
          item.order === 1
            ? 'descending'
            : item.order === 0
              ? 'ascending'
              : undefined
        // console.log(column, tableModel.orderProps)
        return
      }
    }
  }

  return {
    queryModel,
    tableModel,
    upload,
    loading,
    disabled,
    resetColumnSetting,
    saveColumnSetting,
    handleSelectionChange,
    handleHeaderCellClass,
    handleSortChange,
    handleQuery,
    resetQuery,
    fetchTableData,
    pageNumChange,
    pageSizeChange,
    clickTableRow,
    handleDelete,
    handleExport,
    handleUpload,
    closeUpload,
    handleFileUploadProgress,
    handleFileSuccess,
    submitUpload
  }
}
